/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!
  \file			viewimpl.cc
  \date			Dec 2012
  \author		TNick

  \brief		Contains the implementation of ViewImpl class


*//*


 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Please read COPYING and README files in root folder
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include	<cpg/cpg.h>

#include	<cpg/actions/actionshost.h>
#include	<cpg/actions/editorbase.h>
#include	<cpg/settings/apppaths.h>

#include	"viewimpl.h"
#include	<QMessageBox>
#include	<QDir>
#include	<QFileDialog>
#include	<QMenu>
#include	<QToolBar>
#include	<QStyleFactory>
#include	<QSettings>
#include	<QInputDialog>
#include	<QFileInfo>
#include	<QFileInfoList>
#include	<QMenu>
#include	<QDesktopServices>
#include	<QDebug>

/*  INCLUDES    ============================================================ */
//
//
//
//
/*  DEFINITIONS    --------------------------------------------------------- */

#define	SLOT_ENTRY(t)	\
	PGDBG2( PGDBG_A_VIEW, t, this );			\
	EditorBase * ed = host_->crtEditor();		\
	PGDBG2( PGDBG_A_VIEW, "  - document", ed );\
	if ( ed == NULL )	\
	return


/*  DEFINITIONS    ========================================================= */
//
//
//
//
/*  DATA    ---------------------------------------------------------------- */

/*  DATA    ================================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

/* ------------------------------------------------------------------------- */
ViewImpl::ViewImpl		( QObject * parent )
	:QObject( parent ), MemTrack()
{
	PGDBG2( PGDBG_CTORDTOR, "Creating ViewImpl", this );
	host_ = NULL;
	sty_mnu_ = NULL;
	uitpl_mnu_ = NULL;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
ViewImpl::~ViewImpl	( void )
{
	PGDBG2( PGDBG_CTORDTOR, "Destroyng ViewImpl", this );
	if ( sty_mnu_ != NULL )
	{
		delete sty_mnu_;
	}
	if ( uitpl_mnu_ != NULL )
	{
		delete uitpl_mnu_;
	}
}
/* ========================================================================= */

#define	LANG_FILE_PREFIX	"CadPlayG_"
#define	LANG_FILE_SUFFIX	".qm"
#define	LANG_FILE(loc)		(LANG_FILE_PREFIX + loc + LANG_FILE_SUFFIX)

/* ------------------------------------------------------------------------- */
bool						ViewImpl::addLang			(
		const QString & s_lang, const QString & locale )
{
	QString s_label;
	if ( s_lang == "ro_RO" )
	{
		s_label = "Romana";
	}
	else if ( s_lang == "en_US" )
	{
		s_label = "English";
	}
	else
	{
		s_label = locale;
	}
	QAction * act = ui_.menuLanguage->addAction( s_label );
	act->setCheckable( true );
	if ( s_lang == locale )
	{
		act->setChecked( true );
	}
	connect( act, SIGNAL(triggered()),
			 this, SLOT( changeLanguage() ) );
	act->setProperty( "locale", s_lang );
	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool						ViewImpl::init				( ActionsHost * host )
{
	PGDBG2( PGDBG_A_VIEW, "ViewImpl init", this );
	QSettings settings;
	QString stg_val;
	bool b_val;

	host_ = host;
	ui_.setupUi( host->uiParentWidget() );

	connect(ui_.action_LayDir,  SIGNAL(triggered()), this, SLOT(slot_LayDir()));
	connect(ui_.action_No_skin, SIGNAL(triggered()),
			this, SLOT(slot_No_skin()));
	connect(ui_.action_LoadStySh, SIGNAL(triggered()),
			this, SLOT(slot_LoadStySh()));

	connect(ui_.action_ZoomIn, SIGNAL(triggered()),
			this, SLOT(slot_ZoomIn()));
	connect(ui_.action_ZoomOut, SIGNAL(triggered()),
			this, SLOT(slot_ZoomOut()));
	connect(ui_.action_ZoomSet, SIGNAL(triggered()),
			this, SLOT(slot_ZoomSet()));

	ui_.action_No_skin->setWhatsThis( ui_.action_No_skin->toolTip() );
	ui_.action_LoadStySh->setWhatsThis( ui_.action_LoadStySh->toolTip() );
	ui_.action_LayDir->setWhatsThis( ui_.action_LayDir->toolTip() );
	ui_.action_ZoomIn->setWhatsThis( ui_.action_ZoomIn->toolTip() );
	ui_.action_ZoomOut->setWhatsThis( ui_.action_ZoomOut->toolTip() );
	ui_.action_ZoomSet->setWhatsThis( ui_.action_ZoomSet->toolTip() );

	ui_.action_No_skin->setStatusTip( ui_.action_No_skin->toolTip() );
	ui_.action_LoadStySh->setStatusTip( ui_.action_LoadStySh->toolTip() );
	ui_.action_LayDir->setStatusTip( ui_.action_LayDir->toolTip() );
	ui_.action_ZoomIn->setStatusTip( ui_.action_ZoomIn->toolTip() );
	ui_.action_ZoomOut->setStatusTip( ui_.action_ZoomOut->toolTip() );
	ui_.action_ZoomSet->setStatusTip( ui_.action_ZoomSet->toolTip() );


	/* application is translatable */
	QString locale = QSettings().value(
				"language",
				QLocale::system().name()
				).toString();
	addLang( "en_US", locale );
	QDir	dir( AppPaths::unique()->langPath() );

	dir.setFilter( QDir::Files | QDir::NoSymLinks );
	dir.setSorting( QDir::Name );

	QFileInfoList list = dir.entryInfoList();
	for (int i = 0; i < list.size(); ++i)
	{
		QFileInfo fileInfo = list.at(i);
		QString sn = fileInfo.fileName();
		if ( sn.startsWith( LANG_FILE_PREFIX ) )
		{
			if ( sn.endsWith( LANG_FILE_SUFFIX ) )
			{
				int i = sn.length();
				i -= sizeof(LANG_FILE_PREFIX)-1;
				i -= sizeof(LANG_FILE_SUFFIX)-1;
				sn = sn.mid(
							sizeof(LANG_FILE_PREFIX)-1,
							i
							);
				addLang( sn, locale );
			}
		}
	}


	/* style sheets */
	sty_mnu_ = new QMenu( tr( "Style sheets" ) );
	connect(sty_mnu_, SIGNAL(triggered(QAction*)),
			this,SLOT(slot_SkinChange(QAction*)));
	sty_mnu_->addAction( ui_.action_No_skin );
	sty_mnu_->addAction( ui_.action_LoadStySh );
	sty_mnu_->addSeparator();

	settings.beginGroup("ui_style_sheets");
	stg_val = settings.value( "crt_style_sheet" ).toString();
	QDir	dir_ss(QCoreApplication::applicationFilePath());
	dir_ss.cd(QString("../StyleSheets"));
	if (dir_ss.exists())
	{
		QStringList filters;
		filters << "*.css";
		dir_ss.setNameFilters(filters);
		dir_ss.setFilter(QDir::NoDotAndDotDot | QDir::Files | QDir::Readable);
		filters = dir_ss.entryList();
		if (filters.count() > 0)
		{
			for (int i = 0; i < filters.count(); i++)
			{
				QAction* act_in =
						sty_mnu_->addAction( filters.at(i) );
				act_in->setStatusTip(
							tr("StyleSheet located in "
							   "application's predefined folder"));
			}
		}
	}
	if ( stg_val.isEmpty() == false )
	{
		_loadStySh( stg_val );
	}
	settings.endGroup();


	/* ui templates */
	uitpl_mnu_ = new QMenu( tr( "User interface template" ) );
	connect( uitpl_mnu_, SIGNAL( triggered(QAction*) ),
			this,SLOT( slot_UItplChange(QAction*) ) );

	settings.beginGroup( "ui_templates" );
	stg_val = settings.value( "crt_ui_template" ).toString();
	QStringList	sty_list = QStyleFactory::keys();
	/* set b_val to true to change current template */
	if ( stg_val.isEmpty() )
	{
		stg_val = qApp->style()->objectName();
		b_val = false;
	}
	else
	{
		b_val = (
					stg_val.compare(
						qApp->style()->objectName(),
						Qt::CaseInsensitive  ) != 0 );
	}
	for ( int i = 0; i < sty_list.count(); i++ )
	{
		QAction* act_in = uitpl_mnu_->addAction( sty_list.at(i) );
		act_in->setStatusTip( tr( "Predefined skin" ) );
		act_in->setCheckable( true );
		if ( stg_val.compare(
					sty_list.at(i),Qt::CaseInsensitive ) == 0 )
		{ /* a value diffrent from 0 means this is not it */
			if ( b_val )
			{
				qApp->setStyle( stg_val );
			}
			act_in->setChecked( true );
		}
		else
		{
			act_in->setChecked( false );
		}
	}
	settings.endGroup();

	activeEditorChanged( NULL );
	return true;
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void						ViewImpl::end					( void )
{
	QSettings settings;

	settings.beginGroup("ui_style_sheets");
	settings.setValue( "crt_style_sheet", qApp->styleSheet() );
	settings.endGroup();

	settings.beginGroup("ui_templates");
	foreach(QAction* qa, uitpl_mnu_->actions())
	{
		if ( qa->isChecked() )
		{
			settings.setValue( "crt_ui_template", qa->text()  );
			break;
		}
	}
	settings.endGroup();

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void						ViewImpl::initMenu				( QMenu * menu )
{
	menu->addMenu( uitpl_mnu_ );
	menu->addAction( ui_.action_LayDir );
	menu->addMenu( sty_mnu_ );
	menu->addMenu( ui_.menuLanguage );
	menu->addSeparator();
	menu->addAction( ui_.action_ZoomIn );
	menu->addAction( ui_.action_ZoomOut );
	menu->addAction( ui_.action_ZoomSet );

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void						ViewImpl::slot_LayDir            	( void )
{
	PGDBG2( PGDBG_A_VIEW, "ViewImpl layout direction ", this );

	if ( host_->uiParentWidget()->layoutDirection() == Qt::LeftToRight)
	{
		PGDBG( PGDBG_A_VIEW, "  - right to left" );
		qApp->setLayoutDirection(Qt::RightToLeft);
	}
	else
	{
		PGDBG( PGDBG_A_VIEW, "  - left to right" );
		qApp->setLayoutDirection(Qt::LeftToRight);
	}

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void        				ViewImpl::slot_No_skin            ( void )
{
	qApp->setStyleSheet(QString());
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void        				ViewImpl::_loadStySh              (QString fileName)
{
	QString styleSheet;
	QFile   css_file;

	/* read file content */
	css_file.setFileName(fileName);
	if (!css_file.open(QFile::ReadOnly))
	{
		QMessageBox::warning(host_->uiParentWidget(), tr("Error"),
							 tr("Cannot read file %1:\n%2.")
							 .arg(fileName)
							 .arg(css_file.errorString()));
		return;
	}
	styleSheet = QLatin1String(css_file.readAll());
	css_file.close();

	/* and load it's content */
	qApp->setStyleSheet(styleSheet);
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void        				ViewImpl::slot_LoadStySh          ( void )
{
	QFileDialog::Options options;
	QString selectedFilter;
	QString fileName = QFileDialog::getOpenFileName(
				host_->uiParentWidget(),
				tr("Select style sheet to load ..."),
				QString(),
				tr("All Files (*);;Style sheets (*.css)"),
				&selectedFilter,
				options);
	if (!fileName.isEmpty())
	{
		_loadStySh(fileName);
	}
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void        				ViewImpl::slot_SkinChange         (
		QAction * p_active )
{
	QList<QAction *> acls =	sty_mnu_->actions();
	int i = acls.indexOf(p_active);
	if (i < 2)
		return;

	QDir	dir_ss(QCoreApplication::applicationFilePath());
	dir_ss.cd(QString("../StyleSheets"));
	if (dir_ss.exists())
	{
		_loadStySh( dir_ss.absoluteFilePath( p_active->text() ) );
	}

}
/* ========================================================================= */


/* ------------------------------------------------------------------------- */
void						ViewImpl::slot_UItplChange        (
		QAction * p_active )
{
	foreach(QAction* qa, uitpl_mnu_->actions())
	{
		qa->setChecked(false);
	}
	p_active->setChecked(true);
	qApp->setStyle(p_active->text());
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void						ViewImpl::slot_ZoomOut			( void )
{
	SLOT_ENTRY( "ViewImpl: zoom out" );
	ed->zoomOut();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void						ViewImpl::slot_ZoomIn				( void )
{
	SLOT_ENTRY( "ViewImpl: zoom out" );
	ed->zoomIn();
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void						ViewImpl::slot_ZoomSet				( void )
{
	SLOT_ENTRY( "ViewImpl: zoom set" );
	bool b_ok;
	qreal r = ed->crtZoom() * 100;
	qreal i = QInputDialog::getDouble(
				host_->uiParentWidget(),
				tr( "Change zoom factor" ),
				tr(
					"Current zoom is %1.\n"
					"Normal zoom is 100.\n"
					"Smallest zoom unit is 1.\n"
					"\n"
					"Set new zoom factor:"
					)
				.arg( r ),
				r,
				5.0,
				2000.00,
				2,
				&b_ok
				);
	if  ( b_ok )
	{
		PGDBG2( PGDBG_A_VIEW, "  - user input", i );
		ed->setZoom( i / 100.0 );
	}
	else
	{
		PGDBG( PGDBG_A_VIEW, "  - user cancelled the command");
	}

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void						ViewImpl::activeEditorChanged		( EditorBase * ed )
{
	bool with_file = ( ed != NULL );

	ui_.action_ZoomIn->setEnabled( with_file );
	ui_.action_ZoomOut->setEnabled( with_file );
	ui_.action_ZoomSet->setEnabled( with_file );

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
void						ViewImpl::changeLanguage			( void )
{
	QAction * a = static_cast<QAction*>( sender() );

	foreach( QAction * aitr, ui_.menuLanguage->actions() )
	{
		aitr->setChecked( false );
	}

	a->setChecked( true );

	QSettings().setValue(
				"language",
				a->property( "locale" ).toString()
				);

	QMessageBox::information(
				host_->uiParentWidget(), tr( "Language change" ),
				tr(
					"Language change is effective\n"
					"only after restart."
					),
				QMessageBox::Ok );

}
/* ========================================================================= */

/*  CLASS    =============================================================== */
//
//
//
//
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
